package com.ruoyi.course.UtilMCTSCourseScheduling;

import com.ruoyi.classroom.domain.classroom;
import com.ruoyi.classroom.domain.classroom;
import com.ruoyi.course.UtilMCTSCourseScheduling.DataPreprocessor.TimeSlot;
import com.ruoyi.student.domain.StudentInfo;
import com.ruoyi.teacher.domain.teacher;
import com.ruoyi.teacher.domain.teacher;
import com.ruoyi.trainingManagement.domain.CourseScheduleDetails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 统一数据访问接口
 * 职责：封装所有内存Map的查询逻辑，供全流程（包括MctsState）调用
 * 注意：所有Map在初始化后仅提供读取操作，确保数据一致性
 */
@Component
public class DataAccessor {
    private static final Logger logger = LoggerFactory.getLogger(DataAccessor.class);

    // 内存Map（初始化后不可变，仅通过setter设置一次）
    private Map<String, CourseScheduleDetails> courseMap= Collections.emptyMap();           // 课程班ID -> 课程班详情
    private Map<String, teacher> teacherMap;                            // 教师ID -> 教师详情
    private Map<String, classroom> classroomMap;                        // 教室ID -> 教室详情
    private Map<String, StudentInfo> studentMap;                        // 学生ID -> 学生详情
    private Map<String, Set<TimeSlot>> studentTimeSlotMap;              // 学生ID -> 已占用时间槽
    private Map<String, List<String>> courseToStudentsMap;              // 课程班ID -> 学生ID列表
    private Map<String, Set<TimeSlot>> classroomOccupancyMap;           // 教室ID -> 已占用时间槽
    private Map<String, Set<TimeSlot>> teacherOccupancyMap;             // 教师ID -> 已占用时间槽
    /**
     * 核心查询：通过课程班ID获取学生ID列表
     * @param courseClassId 课程班ID
     * @return 学生ID列表（无数据时返回空列表，避免NullPointerException）
     */
    public List<String> getStudentIdsByCourseClassId(String courseClassId) {
        if (courseClassId == null || courseClassId.trim().isEmpty()) {
            logger.warn("获取学生列表失败：课程班ID为空");
            return Collections.emptyList();
        }

        List<String> students = courseToStudentsMap.getOrDefault(courseClassId, Collections.emptyList());
        logger.debug("课程班{}的学生数量：{}", courseClassId, students.size());
        return students;
    }

    /**
     * 通过教师ID获取教师详情
     * @param teacherId 教师ID
     * @return 教师详情（无数据时返回null，需调用方处理）
     */
    public teacher getTeacherById(String teacherId) {
        if (teacherId == null || teacherId.trim().isEmpty()) {
            logger.warn("获取教师详情失败：教师ID为空");
            return null;
        }

        return teacherMap.get(teacherId);
    }

    /**
     * 通过教室ID获取教室详情
     * @param classroomId 教室ID
     * @return 教室详情（无数据时返回null，需调用方处理）
     */
    public classroom getClassroomById(String classroomId) {
        if (classroomId == null || classroomId.trim().isEmpty()) {
            logger.warn("获取教室详情失败：教室ID为空");
            return null;
        }

        return classroomMap.get(classroomId);
    }

    /**
     * 通过课程班ID获取教室信息（适用于已排课的课程班）
     * @param courseClassId 课程班ID
     * @return 教室详情（无数据时返回null，需调用方处理）
     */
    public classroom getClassroomByCourseClassId(String courseClassId) {
        if (courseClassId == null || courseClassId.trim().isEmpty()) {
            logger.warn("查询教室失败：课程班ID为空");
            return null;
        }

        // 1. 获取课程班详情（可能返回null）
        CourseScheduleDetails course = getCourseById(courseClassId);
        if (course == null) {
            // 已在getCourseById中记录错误日志，此处无需重复
            return null;
        }

        // 2. 从课程班详情中获取教室ID（增强校验）
        String classroomId = course.getClassroom();
        if (classroomId == null || classroomId.trim().isEmpty()) {
            logger.debug("课程班{}尚未分配教室（教室ID为空）", courseClassId);
            return null;
        }

        // 3. 通过教室ID获取教室详情（增强校验）
        classroom classroom = getClassroomById(classroomId);
        if (classroom == null) {
            logger.error("教室ID在classroomMap中不存在！classroomId={}, courseClassId={}",
                    classroomId, courseClassId);
        }
        return classroom;
    }

    /**
     * 检查教室在指定时间槽是否可用（无冲突）
     * @param classroomId 教室ID
     * @param timeSlot 时间槽
     * @return true=可用，false=已被占用
     */
    public boolean isClassroomAvailable(String classroomId, TimeSlot timeSlot) {
        if (classroomId == null || timeSlot == null) {
            return false;
        }

        // 获取该教室已占用的时间槽
        Set<TimeSlot> occupiedSlots = classroomOccupancyMap.getOrDefault(classroomId, Collections.emptySet());

        // 检查是否存在时间冲突
        for (TimeSlot occupied : occupiedSlots) {
            if (timeSlot.isSamePeriod(occupied)) {
                logger.debug("教室{}在时间{}已被占用", classroomId, timeSlot);
                return false;
            }
        }
        return true;
    }

    /**
     * 检查教师在指定时间槽是否可用（无冲突）
     * @param teacherId 教师ID
     * @param timeSlot 时间槽
     * @return true=可用，false=已被占用
     */
    public boolean isTeacherAvailable(String teacherId, TimeSlot timeSlot) {
        if (teacherId == null || timeSlot == null) {
            return false;
        }

        // 获取该教师已占用的时间槽
        Set<TimeSlot> occupiedSlots = teacherOccupancyMap.getOrDefault(teacherId, Collections.emptySet());

        // 检查是否存在时间冲突
        for (TimeSlot occupied : occupiedSlots) {
            if (timeSlot.isSamePeriod(occupied)) {
                logger.debug("教师{}在时间{}已被占用", teacherId, timeSlot);
                return false;
            }
        }
        return true;
    }

    /**
     * 检查学生在指定时间槽是否可用（无冲突）
     * @param studentId 学生ID
     * @param timeSlot 时间槽
     * @return true=可用，false=已被占用
     */
    public boolean isStudentAvailable(String studentId, TimeSlot timeSlot) {
        if (studentId == null || timeSlot == null) {
            return false;
        }

        // 获取该学生已占用的时间槽
        Set<TimeSlot> occupiedSlots = getStudentTimeSlots(studentId);

        // 检查是否存在时间冲突
        for (TimeSlot occupied : occupiedSlots) {
            if (timeSlot.isSamePeriod(occupied)) {
                logger.debug("学生{}在时间{}已被占用", studentId, timeSlot);
                return false;
            }
        }
        return true;
    }

    /**
     * 通过学生ID获取已占用时间槽
     * @param studentId 学生ID
     * @return 时间槽集合（无数据时返回空集合，避免NullPointerException）
     */
    public Set<TimeSlot> getStudentTimeSlots(String studentId) {
        if (studentId == null || studentId.trim().isEmpty()) {
            logger.warn("获取学生时间槽失败：学生ID为空");
            return Collections.emptySet();
        }

        return studentTimeSlotMap.getOrDefault(studentId, Collections.emptySet());
    }

    /**
     * 通过课程班ID获取课程详情
     * @param courseClassId 课程班ID
     * @return 课程详情（无数据时返回null，需调用方处理）
     */
    public CourseScheduleDetails getCourseById(String courseClassId) {
        if (courseClassId == null || courseClassId.trim().isEmpty()) {
            logger.warn("获取课程详情失败：课程班ID为空");
            return null;
        }

        return courseMap.get(courseClassId);
    }

    /**
     * 通过学生ID获取学生详情
     * @param studentId 学生ID
     * @return 学生详情（无数据时返回null，需调用方处理）
     */
    public StudentInfo getStudentById(String studentId) {
        if (studentId == null || studentId.trim().isEmpty()) {
            logger.warn("获取学生详情失败：学生ID为空");
            return null;
        }

        return studentMap.get(studentId);
    }

    // Getter和Setter（仅初始化时设置，后续不修改）
    public Map<String, CourseScheduleDetails> getCourseMap() {
        return courseMap;
    }

    public void setCourseMap(Map<String, CourseScheduleDetails> courseMap) {
        // 封装为不可变Map，防止外部修改
        this.courseMap = Collections.unmodifiableMap(courseMap);
    }

    public Map<String, teacher> getTeacherMap() {
        return teacherMap;
    }

    public void setTeacherMap(Map<String, teacher> teacherMap) {
        this.teacherMap = Collections.unmodifiableMap(teacherMap);
    }

    public Map<String, classroom> getClassroomMap() {
        return classroomMap;
    }

    public void setClassroomMap(Map<String, classroom> classroomMap) {
        this.classroomMap = Collections.unmodifiableMap(classroomMap);
    }

    public Map<String, StudentInfo> getStudentMap() {
        return studentMap;
    }

    public void setStudentMap(Map<String, StudentInfo> studentMap) {
        this.studentMap = Collections.unmodifiableMap(studentMap);
    }

    public Map<String, Set<TimeSlot>> getStudentTimeSlotMap() {
        return studentTimeSlotMap;
    }

    public void setStudentTimeSlotMap(Map<String, Set<TimeSlot>> studentTimeSlotMap) {
        this.studentTimeSlotMap = Collections.unmodifiableMap(studentTimeSlotMap);
    }

    public Map<String, List<String>> getCourseToStudentsMap() {
        return courseToStudentsMap;
    }

    public void setCourseToStudentsMap(Map<String, List<String>> courseToStudentsMap) {
        this.courseToStudentsMap = Collections.unmodifiableMap(courseToStudentsMap);
    }

    public Map<String, Set<TimeSlot>> getClassroomOccupancyMap() {
        return classroomOccupancyMap;
    }

    public void setClassroomOccupancyMap(Map<String, Set<TimeSlot>> classroomOccupancyMap) {
        this.classroomOccupancyMap = Collections.unmodifiableMap(classroomOccupancyMap);
    }

    public Map<String, Set<TimeSlot>> getTeacherOccupancyMap() {
        return teacherOccupancyMap;
    }

    public void setTeacherOccupancyMap(Map<String, Set<TimeSlot>> teacherOccupancyMap) {
        this.teacherOccupancyMap = Collections.unmodifiableMap(teacherOccupancyMap);
    }
    // 在DataAccessor类中添加成员变量
    private Map<String, List<String>> studentIdsByCourseClassId;

    // 添加setter方法
    public void setStudentIdsByCourseClassId(Map<String, List<String>> studentIdsByCourseClassId) {
        // 确保外层Map不为null
        this.studentIdsByCourseClassId = new HashMap<>();

        if (studentIdsByCourseClassId != null) {
            // 遍历并确保每个值（学生列表）都不为null
            for (Map.Entry<String, List<String>> entry : studentIdsByCourseClassId.entrySet()) {
                List<String> safeList = entry.getValue() != null ? entry.getValue() : new ArrayList<>();
                this.studentIdsByCourseClassId.put(entry.getKey(), safeList);
            }
        }
    }

    // 可以根据需要添加getter方法
    public Map<String, List<String>> getStudentIdsByCourseClassId() {
        return studentIdsByCourseClassId;
    }
    // 添加根据课程班ID获取学生列表的方法，确保返回非null列表
    public List<String> getStudentsByCourseClassId(String courseClassId) {
        // 如果课程班ID不存在或对应的列表为null，返回空列表
        if (studentIdsByCourseClassId == null) {
            return new ArrayList<>();
        }
        List<String> students = studentIdsByCourseClassId.get(courseClassId);
        return students != null ? students : new ArrayList<>();
    }

}
